﻿using CPF;
using CPF.Animation;
using CPF.Charts;
using CPF.Controls;
using CPF.Drawing;
using CPF.Input;
using CPF.Mac.AppKit;
using CPF.Shapes;
using CPF.Styling;
using CPF.Svg;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Resources;
using System.Text;
using static CPF.Windows.UnmanagedMethods;

namespace CPFUI.IControl
{
    [CPF.Design.DesignerLoadStyle("res://$safeprojectname$/Stylesheet1.css")]//用于设计的时候加载样式
    public class PictrueCropper : Control
    {
        Picture SourcePictrue;
        public PictrueCropper()
        {
            SourcePictrue = new Picture() { 
                MarginLeft= 0,
                MarginRight= 0,
                MarginBottom= 0,
                MarginTop= 0,
                Visibility=Visibility.Collapsed};
            Children.Add(SourcePictrue);

        }
        #region 变量
        /// <summary>
        /// 背景图像
        /// </summary>
        private Bitmap _nonepng;
        /// <summary>
        /// 鼠标按下的焦点
        /// </summary>
        private Point _mouseDownPoint;
        /// <summary>
        /// 鼠标是否按下
        /// </summary>
        private bool _mouseDown;

        /// <summary>
        /// 选择区域的边框范围
        /// </summary>
        private Rect _selectImageBounds;

        /// <summary>
        /// 控件鼠标样式
        /// </summary>
        private SizeGrip _sizeGrip;

        private Rect _selectImageRect;

        #endregion

        /// <summary>
        /// 图片选择范围
        /// 用于计算边线范围和线上小块的位置大小
        /// </summary>
        internal Rect SelectImageRect
        {
            get {
                return _selectImageRect; }
            set
            {
                _selectImageRect = value;
                if (!_selectImageRect.IsEmpty)
                {
                    CalCulateSizeGripRect();
                }
            }
        }

        /// <summary>
        /// 用于存放连线上小块的位置大小
        /// </summary>
        private Dictionary<SizeGrip, Rect> _sizeGripRectList = new Dictionary<SizeGrip, Rect>();


        private CaptureImageToolColorTable _colorTable = new CaptureImageToolColorTable();

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public CaptureImageToolColorTable ColorTable
        {
            get { return _colorTable; }
            set { _colorTable = value; }
        }

        private Image _image24;
        public Image Image24
        {
            get { return _image24; }
            set
            {
                _image24 = value;
            }
        }
        private Image _image60;
        public Image Image60
        {
            get { return _image60; }
            set
            {
                _image60 = value;
            }
        }
        private Image _image100;
        public Image Image100
        {
            get { return _image100; }
            set
            {
                _image100 = value;
            }
        }

        private string _imgPath;
        public object SourceImg
        {
            get { return SourcePictrue.Source; }
            set {
                SetValue(value); 
                SourcePictrue.Source=value;
                SelectImageRect = _selectImageBounds = _selectImageRect;
            }
        }
        public Bitmap GetClicpImage()
        {
            Image bmp = SourcePictrue.GetImage();
            if (bmp == null)
            {
                return null;
            }
            if (bmp != null)
            {
                float w = bmp.Width;
                float h = bmp.Height;

                if (w > h)
                {
                    if (w > this.Width.Value)
                    {
                        h = (int)(h * 1.0f * this.Width.Value / w);
                        w = this.Width.Value;
                    }
                }
                else
                {
                    w = (int)(w * 1.0f * this.Height.Value / h);
                    h = this.Height.Value;
                }
                Rect selectrect = SelectImageRect; 
                float x = selectrect.X / w * bmp.Width;
                float y = selectrect.Y /h * bmp.Height;
                float w1 = selectrect.Width / w * bmp.Width;
                float h1 = selectrect.Height /h * bmp.Height;
                Rect newRect = new Rect(x, y, w1, h1);
                Bitmap temp = new Bitmap((int)newRect.Width, (int)newRect.Height);

                var dc = DrawingContext.FromBitmap(temp);
                {
                    //dc.DrawImage(bmp, new Rect(this.Width.Value / 2 - w / 2, this.Height.Value / 2 - h / 2, w, h), new Rect(0, 0, bmp.Width, bmp.Height));
                    //绘图操作
                    

                    dc.DrawImage(bmp, newRect,new Rect(0, 0, bmp.Width, bmp.Height));
                    return temp;
                }

            }
            return null;
        }
        //模板定义
        protected override void InitializeComponent()
        {
            IsAntiAlias = true;
            _selectImageRect = new Rect(10, 10, this.Width.Value - 20, this.Height.Value - 20);
            SelectImageRect = _selectImageBounds = _selectImageRect;

        }

#if !DesignMode //用户代码写到这里，设计器下不执行，防止设计器出错
        protected override void OnInitialized()
        {
            base.OnInitialized();

        }
        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e); 
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                _mouseDown = true;
                _mouseDownPoint = e.Location;
                Invalidate();
            }
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (_mouseDown)
            {
                ChangeSelctImageRect(e.Location);
                SetSelectRecSite();
                this.Invalidate();
            }
            else
            {
                SetSizeGrip(e.Location);
                Invalidate();
            }
        }


        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            if (e.LeftButton == MouseButtonState.Released)
                _mouseDown = false;

            Invalidate();
        }
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);
            Rect selectrect = SelectImageRect;
            CaptureImageToolColorTable colorTable = ColorTable;
            if (SourceImg != null)
            {
                Image bmp = SourcePictrue.GetImage();
                if (bmp != null)
                {
                    float w = bmp.Width;
                    float h = bmp.Height;

                    if (w > h)
                    {
                        if (w > this.Width.Value)
                        {
                            h = (int)(h * 1.0f * this.Width.Value / w);
                            w = this.Width.Value;
                        }
                    }
                    else
                    {
                        w = (int)(w * 1.0f * this.Height.Value / h);
                        h = this.Height.Value;
                    }
                    dc.DrawImage(bmp, new Rect(this.Width.Value / 2 - w / 2, this.Height.Value / 2 - h / 2, w, h), new Rect(0, 0, bmp.Width, bmp.Height));
                }

            }
            //if (temp != null)
            //{
            //    dc.DrawImage(temp, new Rect(0,0, temp.Width, temp.Height), new Rect(0, 0, temp.Width, temp.Height));
            //}
            using (Brush pen = new SolidColorBrush (colorTable.BorderColor))
            {
                //画外边框线条
                dc.DrawRectangle(pen, new Stroke(1), selectrect);
                #region 画3*3的虚线
                float[] dashPattern = new float[] { 5, 5 };
                float top = selectrect.Height / 3;
                Stroke stroke = new Stroke(1, DashStyles.Custom, 1, dashPattern, CapStyles.Flat);
                    for (int i = 1; i < 3; i++)
                    {
                    dc.DrawLine(stroke, pen,new Point(selectrect.X, selectrect.Y + top * i), new Point(selectrect.X + selectrect.Width, selectrect.Y + top * i));
                    }
                float left = selectrect.Width / 3;
                for (int i = 1; i < 3; i++)
                {
                    dc.DrawLine(stroke, pen, new Point(selectrect.X + left * i, selectrect.Y), new Point(selectrect.X + left * i, selectrect.Y + selectrect.Height));
                }
                #endregion

                #region 画外边框上的九个点
                //画外边框上的九个点
                using (Brush brush = new SolidColorBrush(colorTable.BackColorPressed))
                {
                    foreach (Rect sizeGripRect in _sizeGripRectList.Values)
                    {
                        dc.FillRectangle(brush,sizeGripRect);
                    }
                }
                #endregion
            }
            //绘制选中框以外的遮罩
            if (SelectImageRect.Width != 0 && SelectImageRect.Height != 0)
            {
                //排除选中的方形区域
                //e.Graphics.ExcludeClip(selectrect);
                //排除区域内的圆
                //e.Graphics.ExcludeClip(new Region(DSkin.Common.GraphicsPathHelper.CreatePath(selectrect, selectrect.Width, RoundStyle.All, true)));

                //内部圆形路径
                PathGeometry pathRoundedRect = new PathGeometry(); 

                pathRoundedRect.BeginFigure(selectrect.X + selectrect.Width / 2, selectrect.Y);
                //pathRoundedRect.RectRoundedTo(new CornerRadius(selectrect.Width/2), selectrect);
                pathRoundedRect.ArcTo(new Point(selectrect.X , selectrect.Y +selectrect.Height/2), new Size(selectrect.Width / 2, selectrect.Height / 2), 0, true, true);
                pathRoundedRect.LineTo(0, selectrect.Y + selectrect.Height / 2); 
                pathRoundedRect.LineTo(0,this.Height.Value);
                pathRoundedRect.LineTo(this.Width.Value,this.Height.Value);
                pathRoundedRect.LineTo(this.Width.Value, 0);
                pathRoundedRect.LineTo(selectrect .X+ selectrect .Width/2, 0);
                pathRoundedRect.LineTo(selectrect.X+ selectrect.Width/2, selectrect.Y);
                //pathRoundedRect.ArcTo(new Point(selectrect.X+selectrect.Width/2, selectrect.Y), new Size(selectrect.Width / 2, selectrect.Height / 2), 0, true, true);
                pathRoundedRect.EndFigure(true);

                //内部圆形路径
                PathGeometry pathLeft = new PathGeometry();
                pathLeft.BeginFigure(selectrect.X , selectrect.Y+selectrect.Height/2);
                pathLeft.ArcTo(new Point(selectrect.X + selectrect.Width/2, selectrect.Y), new Size(selectrect.Width / 2, selectrect.Height / 2), 90, true, false);
                pathLeft.LineTo(selectrect.X + selectrect.Width / 2, 0);
                pathLeft.LineTo(0, 0);
                pathLeft.LineTo(0, selectrect.Y + selectrect.Height / 2);
                pathLeft.EndFigure(true);


                PathGeometry pathRight = new PathGeometry();
                pathRight.BeginFigure(selectrect.X + selectrect.Width / 2, selectrect.Y);
                pathRight.ArcTo(new Point(selectrect.X + selectrect.Width , selectrect.Y+ selectrect.Height/2), new Size(selectrect.Width / 2, selectrect.Height / 2), 90, true, false);
                pathRight.LineTo(this.Width.Value, selectrect.Y + selectrect.Height / 2);
                pathRight.LineTo(this.Width.Value, 0);
                pathRight.LineTo(selectrect.X + selectrect.Width / 2, 0);
                pathRight.EndFigure(true);

                PathGeometry pathBottonRight = new PathGeometry();
                pathBottonRight.BeginFigure(selectrect.X + selectrect.Width, selectrect.Y + selectrect.Height / 2);
                pathBottonRight.ArcTo(new Point(selectrect.X + selectrect.Width/2, selectrect.Y + selectrect.Height), new Size(selectrect.Width / 2, selectrect.Height / 2), 90, true, false);
                pathBottonRight.LineTo(selectrect.X + selectrect.Width / 2, this.Height.Value);
                pathBottonRight.LineTo(this.Width.Value, this.Height.Value);
                pathBottonRight.LineTo(this.Width.Value, selectrect.Y + selectrect.Height / 2);
                pathBottonRight.EndFigure(true);

                PathGeometry pathBottonLeft = new PathGeometry();
                pathBottonLeft.BeginFigure(selectrect.X + selectrect.Width / 2, selectrect.Y + selectrect.Height);
                pathBottonLeft.ArcTo(new Point(selectrect.X , selectrect.Y + selectrect.Height/2), new Size(selectrect.Width / 2, selectrect.Height / 2), 90, true, false);
                pathBottonLeft.LineTo(0, selectrect.Y + selectrect.Height / 2);
                pathBottonLeft.LineTo(0, this.Height.Value);
                pathBottonLeft.LineTo(selectrect.X + selectrect.Width / 2, this.Height.Value);
                pathBottonLeft.EndFigure(true);
                List<PathGeometry> paths = new List<PathGeometry>();
                paths.Add(pathLeft);
                paths.Add(pathRight);
                paths.Add(pathBottonRight);
                paths.Add(pathBottonLeft);
                using (Brush brush = new SolidColorBrush(Color.FromArgb(150,0,0,0)))
                {
                    for (int i = 0; i < paths.Count; i++)
                    {
                        dc.FillPath(brush, paths[i]);
                       // dc.DrawPath(brush, new Stroke(1), paths[i]);
                    }
                    //dc.FillPath(brush, pathRoundedRect);
                    //dc.DrawPath(brush,new Stroke(1) , pathRoundedRect2);
                }
            }
        }
        //用户代码
        private void CalCulateSizeGripRect()
        {
            Rect rect = _selectImageRect;

            float x = rect.X;
            float y = rect.Y;
            float centerX = x + rect.Width / 2;
            float centerY = y + rect.Height / 2;


            Dictionary<SizeGrip, Rect> list = _sizeGripRectList;
            list.Clear();

            list.Add(
                SizeGrip.TopLeft,
                new Rect(x - 5, y - 5, 10, 10));
            list.Add(
                SizeGrip.TopRight,
                new Rect(rect.Right - 5, y - 5, 10, 10));
            list.Add(
                SizeGrip.BottomLeft,
                new Rect(x - 5, rect.Bottom - 5, 10, 10));
            list.Add(
                SizeGrip.BottomRight,
                new Rect(rect.Right - 5, rect.Bottom - 5, 10, 10));
            list.Add(
                SizeGrip.Top,
                new Rect(centerX -5, y - 5, 10, 10));
            list.Add(
                SizeGrip.Bottom,
                new Rect(centerX -5, rect.Bottom -5, 10, 10));
            list.Add(
                SizeGrip.Left,
                new Rect(x - 5, centerY - 5, 10, 10));
            list.Add(
                SizeGrip.Right,
                new Rect(rect.Right - 5, centerY - 5, 10, 10));
        }

        //拖动选取区域的方法
        private void ChangeSelctImageRect(Point point)
        {
            Rect rect = _selectImageBounds;
           
            float left = rect.Left;
            float top = rect.Top;
            float right = rect.Right;
            float bottom = rect.Bottom;
            bool sizeGripAll = false;

            switch (_sizeGrip)
            {
                case SizeGrip.All:
                    rect.Offset(
                        point.X - _mouseDownPoint.X, point.Y - _mouseDownPoint.Y);
                    sizeGripAll = true;
                    break;
                case SizeGrip.TopLeft:
                    left = point.X;
                    top = point.Y;
                    break;
                case SizeGrip.TopRight:
                    right = point.X;
                    top = point.Y;
                    break;
                case SizeGrip.BottomLeft:
                case SizeGrip.Left:
                    left = point.X;
                    bottom = point.Y;
                    break;
                case SizeGrip.BottomRight:
                case SizeGrip.Right:
                case SizeGrip.Bottom:
                    right = point.X;
                    bottom = point.Y;
                    break;
                case SizeGrip.Top:
                    right = point.X;
                    top = point.Y;
                    break;
                    //case SizeGrip.Bottom:
                    //    bottom = point.Y;
                    //    break;
                    //case SizeGrip.Left:
                    //    left = point.X;
                    //    break;
                    //case SizeGrip.Right:
                    //    right = point.X;
                    //    break;
            }

            if (!sizeGripAll)
            {
                rect.X = left;
                rect.Y = top;
                rect.Width = (right - left<0)?0: (right - left);
                rect.Height = (bottom - top)<0?0: bottom - top;
            }
            _mouseDownPoint = point;
            _selectImageBounds = rect;
            SelectImageRect = ImageBoundsToRect(rect);
        }


        private void SetSizeGrip(Point point)
        {
            _sizeGrip = SizeGrip.None;
            foreach (SizeGrip sizeGrip in _sizeGripRectList.Keys)
            {
                if (_sizeGripRectList[sizeGrip].Contains(point))
                {
                    _sizeGrip = sizeGrip;
                    break;
                }
            }

            if (_sizeGrip == SizeGrip.None)
            {
                if (SelectImageRect.Contains(point))
                {
                    _sizeGrip = SizeGrip.All;
                }
            }

            switch (_sizeGrip)
            {
                case SizeGrip.TopLeft:
                case SizeGrip.BottomRight:
                    Cursor = Cursors.TopLeftCorner;
                    break;
                case SizeGrip.TopRight:
                case SizeGrip.BottomLeft:
                    Cursor = Cursors.TopRightCorner;
                    break;
                case SizeGrip.Top:
                case SizeGrip.Bottom:
                    Cursor = Cursors.SizeNorthSouth;
                    break;
                case SizeGrip.Left:
                case SizeGrip.Right:
                    Cursor = Cursors.SizeWestEast;
                    break;
                case SizeGrip.All:
                    Cursor = Cursors.SizeAll;
                    break;
                default:
                    Cursor = Cursors.Arrow;
                    break;
            }
        }

        //计算画边线
        private Rect ImageBoundsToRect(Rect bounds)
        {
            Rect rect = bounds;
            float x = 0;
            float y = 0;

            x = Math.Min(rect.X, rect.Right);
            y = Math.Min(rect.Y, rect.Bottom);

            rect.X = x;
            rect.Y = y;

            float rWidth = 0;
            float rHeight = 0;

            rWidth = Math.Max(1, Math.Abs(rect.Width));
            rHeight = Math.Max(1, Math.Abs(rect.Height));
            rect.Width = rect.Height = Math.Max(rWidth, rHeight);

            return rect;
        }

        /// <summary>
        /// 控件选择区域位置
        /// </summary>
        /// <returns></returns>
        private void SetSelectRecSite()
        {
            Rect rect = _selectImageRect;
            bool b = false;
            if (rect.X + rect.Width > this.Width.Value)
            {
                rect.X = this.Width.Value - rect.Width;
                rect.Width = Math.Min(this.Width.Value, rect.Width);
                b = true;
            }
            if (rect.Y + rect.Height > this.Height.Value)
            {
                rect.Y = this.Height.Value - rect.Height;
                rect.Height = Math.Min(this.Height.Value, rect.Height);
                b = true;
            }
            if (rect.X < 0)
            {
                rect.X = 1;
                b = true;
            }
            if (rect.Y < 0)
            {
                rect.Y = 1;
                b = true;
            }
            if (b)
                SelectImageRect = _selectImageBounds = rect;
        }

        public event EventHandler<ImageEventArge> OnSelectedImage;
        private void SelectedImage(Bitmap img)
        {
            if (OnSelectedImage != null)
                OnSelectedImage?.Invoke(this,new ImageEventArge(img));
        }

#endif


    }
    public class ImageEventArge : EventArgs
    {
        public Bitmap Bitmap;
        public ImageEventArge(Bitmap img)
        {
            Bitmap = img;
        }
    }
    public class CaptureImageToolColorTable
    {
        private static readonly Color _borderColor = Color.FromArgb(255,65, 173, 236);
        private static readonly Color _backColorNormal = Color.FromArgb(255, 255, 255, 255);
        private static readonly Color _backColorHover = Color.FromArgb(255, 65, 173, 236);
        private static readonly Color _backColorPressed = Color.FromArgb(255, 24, 142, 206);
        private static readonly Color _foreColor = Color.FromArgb(255, 12, 83, 124);

        public virtual Color BorderColor
        {
            get { return _borderColor; }
        }

        public virtual Color BackColorNormal
        {
            get { return _backColorNormal; }
        }

        public virtual Color BackColorHover
        {
            get { return _backColorHover; }
        }

        public virtual Color BackColorPressed
        {
            get { return _backColorPressed; }
        }

        public virtual Color ForeColor
        {
            get { return _foreColor; }
        }


    }

    internal enum SizeGrip
    {
        None = 0,
        Top,
        Bottom,
        Left,
        Right,
        TopLeft,
        TopRight,
        BottomLeft,
        BottomRight,
        All
    }

}
